package org.osomit.sacct.account.registry.impl;

import org.osomit.sacct.account.registry.iface.AccountRegistry;
import org.osomit.sacct.entity.ApplicationAccountRecord;
import org.osomit.sacct.entity.ApplicationAccount;
import org.osomit.sacct.entity.ApplicationAccountRecordSet;

import java.util.*;

import com.google.inject.Singleton;

/**
 * @author Jian Fang (John.Jian.Fang@gmail.com)
 *
 * Date: Jun 30, 2009
 */
@Singleton
public class InMemoryAccountRegistry implements AccountRegistry {

    private final List<AccountCache> list = Collections.synchronizedList(new LinkedList<AccountCache>());

    protected AccountCache findClient(String clientId){
        AccountCache val = null;

        for(AccountCache cache: list){
            if(clientId.equals(cache.getClientId())){
                val = cache;
                break;
            }
        }

        return val;
    }

    public void addAccount(String clientId, ApplicationAccount account) {

        synchronized (this.list) {
            AccountCache cache = this.findClient(clientId);
            if(cache == null){
                cache = new AccountCache();
                cache.setClientId(clientId);
                this.list.add(cache);
            }
            cache.addOrUpdateAccount(account);
        }
    }

    public void updateAccount(String clientId, ApplicationAccount account) {
        this.addAccount(clientId, account);
    }

    public void deleteAccount(String clientId, String accountName) {

        synchronized (this.list) {
            AccountCache cache = this.findClient(clientId);
            if (cache != null) {
                cache.deleteAccount(accountName);
                if (cache.size() == 0) {
                    this.list.remove(cache);
                }

            }
        }
    }

    public void addAllAccounts(String clientId, List<ApplicationAccount> accounts) {
        synchronized (this.list) {
            AccountCache cache = this.findClient(clientId);
            if(cache == null){
                cache = new AccountCache();
                cache.setClientId(clientId);
                this.list.add(cache);
            }
            cache.addAllAccounts(accounts);
        }
    }

    public ApplicationAccount getAccount(String clientId, String accountName) {
        ApplicationAccount val = null;

        synchronized (this.list) {
            AccountCache cache = this.findClient(clientId);
            if(cache != null){
                val = cache.getAccount(accountName);
            }
        }

        return val;
    }

    public List<ApplicationAccount> getAllAccounts(String clientId) {

        List<ApplicationAccount> val = null;

        synchronized (this.list) {
            AccountCache cache = this.findClient(clientId);
            if(cache != null){
                val = cache.getAllAccounts();
            }
        }

        return val;
    }

    public ApplicationAccountRecordSet getAccountRecordSet() {
        ApplicationAccountRecordSet records = new ApplicationAccountRecordSet();
        List<ApplicationAccountRecord> list = new ArrayList<ApplicationAccountRecord>();

        synchronized (this.list) {
            for(AccountCache cache: this.list){
                list.add(cache.getApplicationAccountRecord());
            }
        }
        
        records.setRecords(list);

        return records;
    }

    public void clear() {
        synchronized (this.list) {
            this.list.clear();
        }
    }
}
